package com.xywh.composeLibrary.statex

import android.util.Log
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems

/**
 * ComposeState
 * @author petterp
 */

/** 状态页data */
sealed class PageData {
    data class Success<T>(val t: T) : PageData()
    data class Error(
        val throwable: Throwable? = null,
        val value: Any? = null
    ) : PageData()

    object Loading : PageData()
    data class Empty(val value: Any? = null) : PageData()
}

/** 页面状态 */
class PageState(state: PageData) {

    /** 内部交互的状态 */
    internal var interactionState by mutableStateOf(state)

    /** 供外部获取当前状态 */
    val state: PageData get() = interactionState

    /** 供外部修改当前状态 */
    fun changeState(pageData: PageData) {
        interactionState = pageData
    }

    val isLoading: Boolean
        get() = interactionState is PageData.Loading

    companion object {
        fun loading() = PageData.Loading

        fun <T> success(t: T) = PageData.Success(t)

        fun empty(value: Any? = null) = PageData.Empty(value)

        fun error(
            throwable: Throwable? = null,
            exceptionMessage: Any? = null
        ) = PageData.Error(throwable, exceptionMessage)
    }
}

@Composable
fun rememberPageState(state: PageData = PageData.Loading): PageState {
    return rememberSaveable {
        PageState(state)
    }
}

@Composable
fun <T : Any> StateCompose(
    lazyPagingItems: LazyPagingItems<T>?,
    state: PageState = PageState(PageState.loading()),
    contentComponentBlock: @Composable () -> Unit
) {
    val contentState = remember { state }

    StateComposeBase(
        modifier = Modifier.fillMaxSize(),
        pageState = contentState,
        lazyPagingItems = lazyPagingItems,
        loading = {
            loadState(lazyPagingItems, contentState)
        },
    ) {
        contentComponentBlock()
    }
}

@Composable
private fun <T : Any> StateComposeBase(
    modifier: Modifier = Modifier,
    pageState: PageState = rememberPageState(),
    lazyPagingItems: LazyPagingItems<T>?,
    loading: () -> Unit,
    loadingComponentBlock: @Composable (BoxScope.() -> Unit)? = StateComposeConfig.loadingComponent,
    emptyComponentBlock: @Composable (BoxScope.(PageData.Empty, onClick: () -> Unit) -> Unit)? = StateComposeConfig.emptyComponent,
    errorComponentBlock: @Composable (BoxScope.(PageData.Error, onClick: () -> Unit) -> Unit)? = StateComposeConfig.errorComponent,
    contentComponentBlock: @Composable (BoxScope.(PageData.Success<T>) -> Unit)
) {
    Box(modifier = modifier) {
        when (pageState.interactionState) {
            is PageData.Success<*> -> contentComponentBlock(pageState.interactionState as PageData.Success<T>)
            is PageData.Loading -> {
                loadingComponentBlock?.invoke(this)
                loading.invoke()
            }

            is PageData.Error -> StateBoxCompose({
                pageState.interactionState = PageData.Loading
            }) {
                errorComponentBlock?.invoke(this, pageState.interactionState as PageData.Error) {
                    Log.e("stateComposeConfig:", "errorComponent--onclick-callback")
                    pageState.changeState(PageState.loading())
                    lazyPagingItems?.retry()
                }
            }

            is PageData.Empty -> emptyComponentBlock?.invoke(
                this,
                pageState.interactionState as PageData.Empty
            ) {
                Log.e("stateComposeConfig:", "emptyComponent--onclick-callback")
                pageState.changeState(PageState.loading())
                lazyPagingItems?.retry()
            }
        }
    }
}

@Composable
private fun StateBoxCompose(block: () -> Unit, content: @Composable BoxScope.() -> Unit) {
    Box(
        Modifier.clickable {
            block.invoke()
        },
        content = content
    )
}


private fun <T : Any> loadState(
    lazyPagingItems: LazyPagingItems<T>?,
    contentState: PageState,
) {
    if (lazyPagingItems != null) {
        when (lazyPagingItems.loadState.refresh) {
            is LoadState.Loading -> {
                contentState.changeState(PageState.loading())
            }

//            is LoadState.NotLoading -> {
//                contentState.changeState(PageState.empty("数据为空"))
//            }

            is LoadState.Error -> {
                contentState.changeState(PageState.error())
            }

            !is LoadState.Loading -> {

                if (lazyPagingItems.itemCount > 0) {
                    contentState.changeState(PageState.success(""))
                } else {
                    contentState.changeState(PageState.empty("数据为空"))
                }
            }


        }
    } else {
        contentState.changeState(PageState.empty())
    }
}




